package com.gitee.cirnochat.user.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gitee.cirnochat.common.exception.BusinessException;
import com.gitee.cirnochat.common.model.enums.ErrorCode;
import com.gitee.cirnochat.user.mapper.FriendApplyMapper;
import com.gitee.cirnochat.user.model.entity.Friend;
import com.gitee.cirnochat.user.model.entity.FriendApply;
import com.gitee.cirnochat.user.model.entity.User;
import com.gitee.cirnochat.user.model.entity.UserPrivacySetting;
import com.gitee.cirnochat.user.model.enums.FriendAddType;
import com.gitee.cirnochat.user.model.vo.req.friend.FriendApplyAddRequest;
import com.gitee.cirnochat.user.model.vo.req.friend.FriendApplyInvitorAddRequest;
import com.gitee.cirnochat.user.model.vo.resp.FriendApplyVo;
import com.gitee.cirnochat.user.service.*;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;

import static com.gitee.cirnochat.user.model.enums.FriendRequestStatus.*;


/**
 * @author FlanChan
 * @description 针对表【friend_request(好友请求记录)】的数据库操作Service实现
 * @createDate 2025-04-17 14:31:33
 */
@Service
@RequiredArgsConstructor
public class FriendApplyServiceImpl extends ServiceImpl<FriendApplyMapper, FriendApply>
        implements FriendApplyService {
    private final UserService userService;
    private final FriendService friendService;
    private final UserPrivacySettingService userPrivacySettingService;
    private final UserBlockListService userBlockListService;

    @Override
    public void sendFriendRequestById(FriendApplyAddRequest req, Long fromId) {
        if (req.getId().equals(fromId)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "不能添加自己为好友");
        }

        if (!userService.existsById(req.getId())) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "接收者不存在");
        }
        // 是否该用户将自己拉黑
        if (userBlockListService.isBlocked(req.getId(),fromId)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "你已被对方拉黑，无法发送好友请求");
        }

        // 判断是否已经是好友
        boolean isFriend = friendService.lambdaQuery()
                .eq(Friend::getUserId, fromId)
                .eq(Friend::getFriendId, req.getId())
                .exists();
        if (isFriend) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "你们已经是好友了");
        }

        // 判断是否已有未处理的请求
        boolean requestExists = this.exists(new LambdaQueryWrapper<FriendApply>()
                .eq(FriendApply::getFromId, fromId)
                .eq(FriendApply::getToId, req.getId())
                .eq(FriendApply::getStatus, PENDING)
        );
        if (requestExists) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "你已发送过好友请求，请等待对方处理");
        }

        // 4. 创建好友请求记录
        FriendApply friendApply = new FriendApply();
        friendApply.setFromId(fromId);
        friendApply.setToId(req.getId());
        friendApply.setMessage(req.getMessage());
        friendApply.setStatus(PENDING);
        friendApply.setType(FriendAddType.QRCODE);
        this.save(friendApply);
    }

    @Override
    public void sendFriendRequestByInvited(FriendApplyInvitorAddRequest req, Long fromId) {
        // 获取当前用户 UUID
        User user = userService.getById(fromId);
        // 当前用户UUID
        String fromUuid = user.getUuid();
        // 接收者 UUID
        String toUuid = req.getId().toString();

        // 自己不能加自己
        if (fromUuid.equals(toUuid)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "不能添加自己为好友");
        }

        //获取接收者
        User toUser = userService.getById(req.getId());
        if (toUser == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "接收者不存在");
        }

        //判断受邀人者是否存在
        User invitor =  userService.getById(req.getInvitorId());
        if (invitor == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "受邀人不存在");
        }

        //获取接收者的隐私设置
        UserPrivacySetting toUserSettings = userPrivacySettingService.getById(toUser.getId());
        // 是否允许通过UUID搜索并添加
        if (!toUserSettings.getSearchableByUuid()) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "对方隐私设置不允许通过UUID添加好友");
        }
        // 是否该用户将自己拉黑
        if (userBlockListService.isBlocked(toUser.getId(), fromId)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "你已被对方拉黑，无法发送好友请求");
        }

        // 判断是否已经是好友
        boolean isFriend = friendService.lambdaQuery()
                .eq(Friend::getUserId, fromId)
                .eq(Friend::getFriendId, toUser.getId())
                .exists();
        if (isFriend) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "你们已经是好友了");
        }

        // 判断是否已有未处理的请求
        boolean requestExists = this.exists(new LambdaQueryWrapper<FriendApply>()
                .eq(FriendApply::getFromId, fromId)
                .eq(FriendApply::getToId, toUser.getId())
                .eq(FriendApply::getStatus, PENDING)
        );
        if (requestExists) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "你已发送过好友请求，请等待对方处理");
        }

        // 4. 创建好友请求记录
        FriendApply friendApply = new FriendApply();
        friendApply.setFromId(fromId);
        friendApply.setToId(toUser.getId());
        friendApply.setMessage(req.getMessage());
        friendApply.setStatus(PENDING);
        friendApply.setInvitorId(req.getInvitorId());
        friendApply.setType(FriendAddType.INVITE);
        this.save(friendApply);
    }

    @Override
    public List<FriendApplyVo> listFriendRequests(Long userId) {
        List<FriendApplyVo> friendApplyVos = this.baseMapper.selectFriendRequests(userId);
        return friendApplyVos.isEmpty() ? List.of() : friendApplyVos;
    }

    @Override
    public Long countFriendRequests(Long userId) {
       return this.count(new LambdaUpdateWrapper<>(FriendApply.class)
                .eq(FriendApply::getToId, userId)
                .eq(FriendApply::getStatus, PENDING));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void acceptFriendRequest(Long requestId,Long fromId) {
        FriendApply friendApply = this.getById(requestId);
        if (friendApply == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "请求不存在");
        }

        if (!friendApply.getToId().equals(fromId)) {
            throw new BusinessException(ErrorCode.FORBIDDEN_ERROR, "无权限操作");
        }

        if (REJECTED.equals(friendApply.getStatus())) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "请求已拒绝");
        }

        if (ACCEPTED.equals(friendApply.getStatus())) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "请求已接受");
        }

        // 更新状态
        this.update(new LambdaUpdateWrapper<FriendApply>()
                .eq(FriendApply::getFromId, friendApply.getFromId())
                .eq(FriendApply::getToId, friendApply.getToId())
                .eq(FriendApply::getStatus, PENDING)
                .set(FriendApply::getStatus, ACCEPTED));
        this.update(new LambdaUpdateWrapper<>(FriendApply.class)
                .eq(FriendApply::getFromId, friendApply.getToId())
                .eq(FriendApply::getToId, friendApply.getFromId())
                .eq(FriendApply::getStatus, PENDING)
                .set(FriendApply::getStatus, ACCEPTED));

        // 双向添加好友
        Friend f1 = new Friend();
        f1.setUserId(friendApply.getFromId());
        f1.setFriendId(friendApply.getToId());

        Friend f2 = new Friend();
        f2.setUserId(friendApply.getToId());
        f2.setFriendId(friendApply.getFromId());

        friendService.saveBatch(Arrays.asList(f1, f2));
    }


    @Override
    public void rejectFriendRequest(Long requestId, Long fromId) {
        FriendApply friendApply = this.getById(requestId);
        if (friendApply == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "请求不存在");
        }
        if (!friendApply.getToId().equals(fromId)) {
            throw new BusinessException(ErrorCode.FORBIDDEN_ERROR, "无权限操作");
        }

        if (!PENDING.equals(friendApply.getStatus())) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "请求已处理");
        }
        friendApply.setStatus(REJECTED);
        this.updateById(friendApply);
    }


    @Override
    public void revokeFriendRequest(Long requestId, Long fromId) {
        FriendApply friendApply = this.getById(requestId);
        if (friendApply == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "请求不存在");
        }
        if (!friendApply.getFromId().equals(fromId)) {
            throw new BusinessException(ErrorCode.FORBIDDEN_ERROR, "无权限操作");
        }

        this.removeById(requestId);
    }

}




